package com.xavier.dong.netty.codec;

import com.xavier.dong.grpc.pojo.StudentPOJO;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.CharsetUtil;

/**
 * 说明：
 * 1. 我们自定义一个 handler 需要继承 Netty 规定好的 某个 Handler 适配器
 * 2. 这时，我们 自定义的 Handler 才能成为 一个 Handler
 *
 * @author XavierDong
 **/
public class NettyServerHandler extends ChannelInboundHandlerAdapter {


    /**
     * 读取数据实际 （这里我们可以读取 客户端的消息）
     *
     * @param ctx 上下文对象，含有  管道(pipeline) ，通道(channel)，地址
     * @param msg 客户端 发送的数据, 默认是 Object
     * @throws Exception
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {

        // 读取 从客户端的消息
        StudentPOJO.Student student = (StudentPOJO.Student) msg;

        // 客户端发送的数据
        System.out.println("客户端发送的数据：id=" + student.getId() + "名字=" + student.getName());


        // 比如 我们这里 一个非常耗时 的业务 -> 异步执行 -> 提交 该 channel 对应的 NIOEventLoop 中
//        TimeUnit.SECONDS.sleep(10);
//        ctx.writeAndFlush(Unpooled.copiedBuffer("客户端 喵喵~~~~~~2", CharsetUtil.UTF_8));


        // 解决方案 一 用户自定义的普通任务
        // 在 TaskQueue 中 。 10秒 后 返回
//        ctx.channel().eventLoop().execute(() -> {
//            try {
//                TimeUnit.SECONDS.sleep(10);
//                ctx.writeAndFlush(Unpooled.copiedBuffer("客户端 喵喵~~~~~~2", CharsetUtil.UTF_8));
//            } catch (InterruptedException e) {
//                System.out.println("发生异常 " + e.getMessage());
//            }
//        });
//
//        // 在 TaskQueue 中 。 10+20=30秒 后 才返回 （就是因为 他们 是 同一个 线程！）
//        ctx.channel().eventLoop().execute(() -> {
//            try {
//                TimeUnit.SECONDS.sleep(20);
//                ctx.writeAndFlush(Unpooled.copiedBuffer("客户端 喵喵~~~~~~3", CharsetUtil.UTF_8));
//            } catch (InterruptedException e) {
//                System.out.println("发生异常 " + e.getMessage());
//            }
//        });
//
//
//        // 解决 方案二  用户自定义定时任务---> 该任务 提交到 scheduleTaskQueue
//        ctx.channel().eventLoop().schedule(() -> {
//            try {
//                TimeUnit.SECONDS.sleep(10);
//                ctx.writeAndFlush(Unpooled.copiedBuffer("客户端 喵喵~~~~~~4", CharsetUtil.UTF_8));
//            } catch (InterruptedException e) {
//                System.out.println("发生异常 " + e.getMessage());
//            }
//        }, 5, TimeUnit.SECONDS);

        System.out.println("go on .....");


//
//        System.out.println("服务器读取线程 "+Thread.currentThread().getName());
//        System.out.println("Server ctx=" + ctx);
//
//        System.out.println("看看 channel 和 pipeline 的关系");
//
//        Channel channel = ctx.channel();
//        ChannelPipeline pipeline = ctx.pipeline(); // 本质是一个 双向链表，涉及到 出站和入站
//
//
//        // 将 msg 转为 ByteBuffer
//        // ByteBuf 是 Netty 提供的, 不是 NIO 的 ByteBuffer
//        ByteBuf byteBuf = (ByteBuf) msg;
//
//        System.out.println("客户端发送消息是: " + byteBuf.toString(CharsetUtil.UTF_8));
//        System.out.println("客户端地址：" + ctx.channel().remoteAddress());
    }

    /**
     * 数据 读取 完毕
     *
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {

        // writeAndFlush 是 write + Flush
        // 将 数据 写入 缓存，并 刷新
        // 一般 将 对 发送的 数据 进行 编码
        ctx.writeAndFlush(Unpooled.copiedBuffer("hello，客户端 ~~~~ 喵喵", CharsetUtil.UTF_8));

    }

    /**
     * 异常的处理, 出现异常，需要 关闭 通道
     *
     * @param ctx
     * @param cause
     * @throws Exception
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        ctx.close();
    }
}
